package com.dq.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.java.Log;
import org.apache.commons.codec.binary.Base64;

import javax.imageio.ImageIO;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author liuhui
 * @date 2019/9/29 0029 19:56:30
 *
 *  小程序的工具类封装   配置小程序的id和  密匙,请求路径之类的
 */
@Log
public class SmallQrCode {
    private static final String appid = "wx1281f9eefba5a8ab";  // 根据不同的小程序appid填写，一下同理
    private static final String secret = "82a09af11e42f656d2547dc83042eaa2";
    private static final String accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token";

    public static String getAccessToken(){
        Map<String, String> requestParam = new HashMap<String,String>();
        requestParam.put("grant_type", "client_credential");
        requestParam.put("appid", appid);
        requestParam.put("secret", secret);
        // sendPost 为一个请求各种接口而封装的函数，并转换JSON字符串为JSONObject
        JSONObject jsonObject = JSON.parseObject(sendPost(accessTokenURL, requestParam));
        String access_token = jsonObject.getString("access_token");
        return access_token;
    }

    public static void main(String[] args) {
        System.out.println(SmallQrCode.getAccessToken());
    }
    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url 发送请求的 URL
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, Map<String, ?> paramMap) {
        //URLConnection conn = null;  // 默认返回 HTTPS
        HttpURLConnection conn = null;  // 默认返回HTTP，用爸爸接收返回数据
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";

        String param = "";
        Iterator<String> it = paramMap.keySet().iterator();

        while(it.hasNext()) {
            String key = it.next();
            param += key + "=" + paramMap.get(key) + "&";
        }

        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            conn = (HttpURLConnection) realUrl.openConnection();  // 返回对象为 HttpsURLConnection,儿子的儿子
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 超时设置,防止 网络异常的情况下,可能会导致程序僵死而不继续往下执行
            conn.setConnectTimeout(3000);
            conn.setReadTimeout(3000);
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
                if(conn !=null){
                    conn.disconnect();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;  // 返回的为JSON字符串
    }

    /**
     * 获取小程序码
     */
    public static  String getWXQrcode(String access_token, String page, String scene, Integer width) {
        String qrcodeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";  // 获取小程序码的接口头部
        String url = qrcodeUrl+"?access_token="+access_token;  // 拼接完整的URl
        Map<String, Object> requestParam = new HashMap<String,Object>();  // 小程序的参数可查看官方文档
        if(page!= null) {requestParam.put("page", page);}  // 扫码后需要跳转的页面
        if(scene!= null) {requestParam.put("scene", scene);}  // 携带的参数
        if(width!= null) {requestParam.put("width", width); } // 二维码的宽度
        String param = JSON.toJSONString(requestParam);

        // 使用 RestTemplate 出现的问题，用该类代码会更简洁
        // rest debugger发过来的content-type为application/json，而jq的多了charset=utf-8
        // Could not read document: Invalid UTF-8 middle byte 0xff
	/*JSONObject jsonObject =
			restTemplate.postForObject(url, param, JSONObject.class);
	System.out.println(jsonObject.toJSONString());*/

        HttpURLConnection conn = null;
        BufferedReader bufferedReader = null;
        PrintWriter out = null;
        InputStream in = null;
        ByteArrayOutputStream bos = null;
        String base64String = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            conn = (HttpURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 超时设置,防止 网络异常的情况下,可能会导致程序僵死而不继续往下执行
            conn.setConnectTimeout(3000);
            conn.setReadTimeout(3000);
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();

            in = conn.getInputStream();  // 得到图片的二进制内容
            int leng = in.available();  // 获取二进制流的长度，该方法不准确
            if(leng < 1000){  // 出现错误时，获取字符长度就一百不到，图片的话有几万的长度
                // 定义BufferedReader输入流来读取URL的响应
                bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String line;
                String result = "";
                while ((line = bufferedReader.readLine()) != null) {
                    result += line;
                }
                log.info("获取access_token出错："+result);
                // 清空 access_token 缓存
                return result;
            }

            // 修改图片的分辨率,分辨率太大打印纸不够大
            //BufferedInputStream in2 = new BufferedInputStream(conn.getInputStream());
            // 将文件二进制流修改为图片流
            Image srcImg = ImageIO.read(in);
            // 构建图片流
            BufferedImage buffImg = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
            //绘制改变尺寸后的图
            buffImg.getGraphics().drawImage(srcImg.getScaledInstance(width, width, Image.SCALE_SMOOTH), 0, 0, null);
            // 将图片流修改为文件二进制流
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(buffImg, "png", os);
            in = new ByteArrayInputStream(os.toByteArray());
            // 刷新，将重置为类似于首次创建时的状态
            buffImg.flush();
            srcImg.flush();
            // 设null是告诉jvm此资源可以回收
            buffImg = null;  // 该io流不存在关闭函数
            srcImg = null;  // 该io流不存在关闭函数
            os.close();

            bos = new ByteArrayOutputStream();
            byte[] b1 = new byte[1024];
            int len = -1;
            while((len = in.read(b1)) != -1) {
                bos.write(b1, 0, len);
            }
            byte[] fileByte = bos.toByteArray();  // 转换为字节数组，方便转换成base64编码

            //BASE64Encoder encoder = new BASE64Encoder();   // import sun.misc.BASE64Encoder;  该类包为内部专用以后可能会删除，sun公司
            // 对字节数组转换成Base64字符串
            //base64String = encoder.encode(fileByte);

            base64String = Base64.encodeBase64String(fileByte);  // import org.apache.commons.codec.binary.Base64;
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try {
                if(bufferedReader != null){
                    bufferedReader.close();
                }
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
                if(bos != null){
                    bos.close();
                }
                if(conn !=null){
                    conn.disconnect();
                    conn = null;
                }
                //让系统回收资源，但不一定是回收刚才设成null的资源，可能是回收其他没用的资源。
                System.gc();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return base64String;  // 将base64格式的图片发送到前端
    }


}


